﻿namespace _4_NovaAdmin.Web.Core.ServiceExtensions;

/// <summary>
/// Startup扩展
/// </summary>
public static class StartupSetup
{

    /// <summary>
    /// ConfigureServices调用
    /// </summary>
    /// <param name="services"></param>
    public static void AddServices(this IServiceCollection services, IConfiguration configuration)
    {
        CallStartupMethods(services, "ConfigureServices", configuration);
    }

    /// <summary>
    /// Configure调用
    /// </summary>
    /// <param name="app"></param>
    public static void AddConfigure(this IApplicationBuilder app, IConfiguration configuration)
    {
        CallStartupMethods(app, "Configure", configuration);
    }

    /// <summary>
    /// 将Json配置合并
    /// </summary>
    /// <param name="app"></param>
    public static void LoadJsonConfig(this WebApplicationBuilder builder)
    {
        var configurationPath = Path.Combine(System.AppContext.BaseDirectory, "Configuration");
        var jsonFiles = Directory.EnumerateFiles(configurationPath, "*.json");

        foreach (var jsonFile in jsonFiles)
        {
            builder.Configuration.AddJsonFile(jsonFile, optional: true);
        }
    }

    /// <summary>
    /// Add services to the container
    /// Configure the HTTP request pipeline
    /// </summary>
    /// <param name="parameter"></param>
    /// <param name="methodName"></param>
    private static void CallStartupMethods(object parameter, string methodName, IConfiguration configuration)
    {
        // 1. 所有 AppStartup 派生类和 Order 值
        var startupTypes = new List<(Type Type, int Order)>();

        foreach (var assembly in GlobalAssemblies.AllAssemblies)
        {
            Type? type = assembly.GetTypes().Where(type => type.IsSubclassOf(typeof(AppStartup)) && !type.IsAbstract).FirstOrDefault();
            if (type != null)
            {
                // 获取 Order 值（默认为 0）
                var order = type.GetCustomAttribute<AppStartupAttribute>()?.Order ?? 0;
                startupTypes.Add((type, order));
            }
        }

        // 2. 按 Order 降序排序（数值大的先执行）
        var orderedStartupTypes = startupTypes
            .OrderByDescending(x => x.Order)
            .ThenBy(x => x.Type.FullName) // 如果 Order 相同，按类型名排序
            .ToList();

        // 3. 按顺序执行
        foreach (var (type, _) in orderedStartupTypes)
        {
            // 创建实例
            var startupInstance = Activator.CreateInstance(type);

            // 注入配置
            InjectConfigurationByProperty(startupInstance, configuration);

            // 调用方法
            var method = type.GetMethod(methodName)
                ?? throw new InvalidOperationException($"Method '{methodName}' not found in type '{type.Name}'.");

            method.Invoke(startupInstance, new[] { parameter });
        }
    }

    /// <summary>
    /// 通过反射将 IConfiguration 注入到 Startup 类的属性
    /// </summary>
    /// <param name="instance"></param>
    /// <param name="configuration"></param>
    private static void InjectConfigurationByProperty(object instance, IConfiguration configuration)
    {
        var property = instance.GetType().GetProperty("config");
        if (property != null &&
            property.PropertyType == typeof(IConfiguration) &&
            property.CanWrite)
        {
            property.SetValue(instance, configuration);
        }
    }
}
